import {
  RequestParams,
  UdfResponse,
  UdfErrorResponse,
  logMessage
} from "./helpers";
export class Requester {
  private _headers: HeadersInit | undefined;

  private opts: any;

  private urlSymbol: any = "";

  public constructor(opts: any, headers?: HeadersInit) {
    this.opts = opts;
    this.setSymbol(this.opts.symbol);
    if (headers) {
      this._headers = headers;
    }
  }

  public sendRequest<T extends UdfResponse>(
    datafeedUrl: string,
    urlPath: string,
    params?: RequestParams
  ): Promise<T | UdfErrorResponse>;
  public sendRequest<T>(
    datafeedUrl: string,
    urlPath: string,
    params?: RequestParams
  ): Promise<T>;
  public sendRequest<T>(
    datafeedUrl: string,
    urlPath: string,
    params?: RequestParams
  ): Promise<T> {
    const before: any = this._adaptBefore(urlPath, params);
    urlPath = before.urlPath + "/" + this.urlSymbol;
    params = before.params;
    if (params !== undefined) {
      const paramKeys = Object.keys(params);
      if (paramKeys.length !== 0) {
        urlPath += "?";
      }

      urlPath += paramKeys
        .map((key: string) => {
          return `${encodeURIComponent(key)}=${encodeURIComponent(
            before.params[key].toString()
          )}`;
        })
        .join("&");
    }

    logMessage("New request: " + urlPath);

    // Send user cookies if the URL is on the same origin as the calling script.
    const options: RequestInit = { credentials: "same-origin" };

    if (this._headers !== undefined) {
      options.headers = this._headers;
    }
    return fetch(`${datafeedUrl}/${urlPath}`, options)
      .then((response: Response) => {
        return response.text();
      })
      .then((responseTest: string) => {
        const ret = this.opts.tldebug
          ? JSON.parse(responseTest)
          : JSON.parse(responseTest).data;
        return ret;
      });
  }

  public setSymbol(symbol: any): void {
    this.urlSymbol = symbol;
  }

  private _adaptBefore(urlPath: string, params?: RequestParams) {
    if (urlPath === "config") {
      return this._bebforeConfig(urlPath, params);
    }

    if (urlPath === "symbol_info") {
      return this._beforeSymbolInfo(urlPath, params);
    }

    if (urlPath === "time") {
      return this._beforeTime(urlPath, params);
    }

    if (urlPath === "symbols") {
      return this._beforeSymbols(urlPath, params);
    }

    if (urlPath === "history") {
      return this._beforeHistory(urlPath, params);
    }

    return {
      urlPath,
      params
    };
  }

  private _bebforeConfig(urlPath: string, params?: RequestParams) {
    return {
      urlPath: "quote/tv/config",
      params
    };
  }

  private _beforeSymbolInfo(urlPath: string, params?: RequestParams) {
    return {
      urlPath: "quote/tv/symbolInfo",
      params: params ? { symbol: params.group } : undefined
    };
  }

  private _beforeSymbols(urlPath: string, params?: RequestParams) {
    return {
      urlPath: "quote/tv/symbolInfo",
      params
    };
  }

  private _beforeTime(urlPath: string, params?: RequestParams) {
    return {
      urlPath: "quote/tv/getServerTime",
      params
    };
  }

  private _beforeHistory(urlPath: string, params?: RequestParams) {
    return {
      urlPath: "quote/tv/getBars",
      params
    };
  }
}
